package com.taotao.manage.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.taotao.common.bean.ItemCatData;
import com.taotao.common.bean.ItemCatData2;
import com.taotao.common.bean.ItemCatResult;
import com.taotao.common.service.RedisService;
import com.taotao.manage.pojo.ItemCat;

@Service
public class ItemCatService extends BaseService<ItemCat> {
	@Autowired
	private RedisService shardedJedisPoolService;//使用jedis添加缓存
	@Autowired
	private PropertiesService propertiesService;

	/**
	 * @Description:封装成如下格式的数据
	 * 				"data": [
	    {
	        "u": "/products/1.html",                                     //一级目录的url
	        "n": "<a href='/products/1.html'>图书、音像、电子书刊</a>",  //一级目录的name
	        "i": [                                                       //一级目录包含的二级目录集合
	            {
	                "u": "/products/2.html",  					//二级目录的url
	                "n": "电子书刊",          					//二级目录的name
	                "i": [                    					//二级目录包含的三级目录集合
	                    "/products/3.html|电子书",		//三级目录
	                    "/products/4.html|网络原创",
	                    "/products/5.html|数字杂志",
	                    "/products/6.html|多媒体图书"
	                ]
	            },
	 * @return
	 * @author mingxu
	 * 
	 * 
	 * 	总结：
	 * 		1、查询所有商品类目，目的是解决for循环查询效率低下问题
	 * 		2、为商品类目制作映射表，父目录id为key,对应id下商品类目集合为value
	 * 		3、准备三层树形结构容器
	 * 		4、逐层封装数据：先提供容器，再进行数据封装
	 */
	public ItemCatResult queryAllToTree() {

		//0、查看缓存中是否已经有数据，命中缓存则直接返回，没有命中则查询数据库，最后将数据存储到缓存中
		//缓存机制一定不能影响程序正常运行，所以需要捕获异常
		String key = propertiesService.REDIS_ITEM_CAT_ALL_KEY;
		try {
			//获取缓存
			String redisResult = shardedJedisPoolService.get(key);
			if (StringUtils.isNotEmpty(redisResult)) {
				//命中缓存后转换成对象返回
				return PropertiesService.MAPPER.readValue(redisResult, ItemCatResult.class);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		//1、查询所有商品类目
		List<ItemCat> itemCatAll = super.queryAll();

		//2、将所有商品类目添加到映射表中，父目录id为id,parent_id作为索引，可以快速定位到商品类目集合，对应id下商品类目集合为value
		Map<Long, List<ItemCat>> map = new HashMap<Long, List<ItemCat>>();

		// 将所有的商品类目，封装到映射表中
		for (ItemCat itemCat : itemCatAll) {
			//如果当前商品类目的父目录不存在与映射表中，就添加一条映射
			if (!map.containsKey(itemCat.getParentId())) {
				map.put(itemCat.getParentId(), new ArrayList<ItemCat>());
			}

			//如果当前商品类目的父目录存在，直接将当前商品类目添加到当前parnet_id对应的商品类目集合中
			List<ItemCat> list = map.get(itemCat.getParentId());
			list.add(itemCat);
		}

		//3、从映射表中查询数据，并将数据按照前台所需的三层树形结构进行封装

		//先提供一级目录容器
		ItemCatResult itemCatResult = new ItemCatResult();
		List<ItemCatData> itemCatDataList = new ArrayList<ItemCatData>();
		itemCatResult.setItemCatDataList(itemCatDataList);

		//再进行封装
		//4、封装一级目录到容器中

		//从映射表中查询所有的一级目录，并遍历
		List<ItemCat> ic1List = map.get(0L);

		for (ItemCat ic1 : ic1List) {
			//如果当前一级目录不是父目录，就不需要封装到一级目录容器，直接跳过本次循环，可以提升效率
			if (!ic1.getIsParent()) {
				continue;
			}

			//封数据到对象中
			ItemCatData itemCatData = new ItemCatData();
			itemCatData.setUrl("/products/" + ic1.getId() + ".html");
			itemCatData.setName("<a href='/products/" + ic1.getId() + ".html'>" + ic1.getName() + "</a>");

			//装对象到一级目录容器
			itemCatDataList.add(itemCatData);

			//5、封装二级目录到容器中

			//提供二级目录容器
			List<ItemCatData2> itemCatData2List = new ArrayList<ItemCatData2>();
			itemCatData.setItems(itemCatData2List);

			//从映射表中获取当前一级目录下所有的二级目录，并遍历
			List<ItemCat> ic2List = map.get(ic1.getId());
			for (ItemCat ic2 : ic2List) {
				//如果当前二级目录不是父目录，就不需要封装到二级目录容器，直接跳过本次循环，可以提升效率
				if (!ic1.getIsParent()) {
					continue;
				}

				//封数据到对象中
				ItemCatData2 itemCatData2 = new ItemCatData2();
				itemCatData2.setUrl("/products/" + ic2.getId() + ".html");
				itemCatData2.setName(ic2.getName());

				//装对象到二级目录容器中
				itemCatData2List.add(itemCatData2);

				//6、封装三级目录到容器中

				//提供三级目录容器
				List<String> strList = new ArrayList<String>();
				itemCatData2.setItems(strList);

				//从映射表中查询当前二级类目下所有的三级类目，并遍历
				List<ItemCat> ic3List = map.get(ic2.getId());
				for (ItemCat ic3 : ic3List) {
					//直接封装三级目录到三级类目容器中
					strList.add("/products/" + ic3.getId() + ".html|" + ic3.getName() + "");
				}
			}
		}

		//7、将查询到的所有商品类目信息存储到缓存中
		try {
			String value = PropertiesService.MAPPER.writeValueAsString(itemCatResult);
			int time = Integer.parseInt(propertiesService.REDIS_ITEM_CAT_ALL_TIME);
			String setex = shardedJedisPoolService.setex(key, time, value);
			System.out.println(setex);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return itemCatResult;

	}
}
